package com.bridgeintelligent.tag.engine.mvc.service;

import com.bridgeintelligent.tag.engine.api.IndexNameInfo;
import com.bridgeintelligent.tag.engine.api.rsp.DimAnalysisRsp;
import com.bridgeintelligent.tag.engine.es.model.DimMonitorDetailModel;
import com.bridgeintelligent.tag.engine.es.model.GroupItem;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.range.DateRangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregator;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description
 * @author: grp 2020-11-02 13:55
 **/
public interface IMonitorService {
    default Double getValue(String D1) {
        String[] array = D1.split("~");
        if(D1.indexOf("-")==0){
            if(StringUtils.equals("-∞",array[0])){
                return Double.MIN_VALUE;
            }
            return Double.parseDouble(array[0]);
        }else{
            if(StringUtils.equals("+∞",array[0]) || StringUtils.equals("∞",array[0])){
                return Double.MAX_VALUE;
            }
            return Double.parseDouble(array[0]);
        }
    }

    default String getTitle(String date, DateHistogramInterval interval){
        if(interval.equals(DateHistogramInterval.YEAR)){
            DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")).plusYears(1).toString("yyyy-MM-dd");
            return date+"/"+DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")).plusYears(1).toString("yyyy-MM-dd");
        }
        if(interval.equals(DateHistogramInterval.MONTH)){
            DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")).plusMonths(1).toString("yyyy-MM-dd");
            return date+"/"+DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")).plusMonths(1).toString("yyyy-MM-dd");
        }
        String inter = interval.toString();
        String start = date;
        if(StringUtils.startsWith(date, "-")){
            // 最小日期
            start = "0001-01-01";
        }
        return start+"/"+DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")).plusDays(Integer.parseInt(inter.substring(0, inter.length()-1))).toString("yyyy-MM-dd");
    }

    default BoolQueryBuilder getBoolQueryBuilder(String dimIdColumn) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(
                QueryBuilders.boolQuery()
                        .should(QueryBuilders.boolQuery().must(QueryBuilders.existsQuery(dimIdColumn))
                        ));
        return boolQueryBuilder;
    }

    default BoolQueryBuilder getBoolQueryBuilder1(String dimId,List<String> dates) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        for (String date:dates) {
            boolQueryBuilder.should(QueryBuilders.existsQuery(dimId+"_"+date));
        }
        return boolQueryBuilder;
    }

    default Set<String> getFields(String dimId,List<String> dates) {
        Set<String> fieldsSet = new HashSet<>();
        for (String date:dates) {
            fieldsSet.add(dimId+"_"+date);
        }
        return fieldsSet;
    }

    default RangeAggregationBuilder getNumberAggregation(List<GroupItem> items, String dimId) {
        RangeAggregationBuilder rangeBuilder = AggregationBuilders.range("count").field(dimId);
        for(GroupItem item:items){
            Double low=null;
            Double high=null;
            if(StringUtils.isNotBlank(item.getLow())&&!StringUtils.equals(item.getLow(),"-∞")){
                low = new Double(item.getLow());
            }
            if(StringUtils.isNotBlank(item.getHigh())&&!StringUtils.equals(item.getHigh()," ∞")&&!StringUtils.equals(item.getHigh(),"+∞")){
                high = new Double(item.getHigh());
            }else{
                item.setHigh("+∞");
            }
            RangeAggregator.Range range = new RangeAggregator.Range(item.getLow()+"~"+item.getHigh(), low, high);
            rangeBuilder.addRange(range);
        }
        return rangeBuilder;
    }

    default DateRangeAggregationBuilder getDateAggregation(List<GroupItem> items, String dimId) {
        DateRangeAggregationBuilder rangeBuilder = AggregationBuilders.dateRange("count").field(dimId);
        for(GroupItem item:items){
            String low = "";
            String high= "";
            if (!StringUtils.isEmpty(item.getLow()) && !StringUtils.equals(item.getLow(),"-∞")){
                low = LocalDate.parse(item.getLow(), DateTimeFormatter.BASIC_ISO_DATE).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            }else {
                item.setLow("-∞");
            }
            if (!StringUtils.isEmpty(item.getHigh()) && !StringUtils.equals(item.getHigh()," ∞")&&!StringUtils.equals(item.getHigh(),"+∞")){
                high = LocalDate.parse(item.getHigh(), DateTimeFormatter.BASIC_ISO_DATE).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            }else{
                item.setHigh("+∞");
            }
            if (!StringUtils.equals(item.getLow(),"-∞") && !StringUtils.equals(item.getHigh(),"+∞")){
                rangeBuilder.addRange(low+" / "+high,low,high);
            }else if (StringUtils.equals(item.getLow(),"-∞") && !StringUtils.equals(item.getHigh(),"+∞")){
                rangeBuilder.addUnboundedTo("-∞ / "+high,high);
            }else if (!StringUtils.equals(item.getLow(),"-∞") && StringUtils.equals(item.getHigh(),"+∞")){
                rangeBuilder.addUnboundedFrom(low+" / +∞",low);
            }
        }
        return rangeBuilder;
    }

    default SearchRequest getCustomizeNumberSearchRequest(IndexNameInfo indexNameInfo, String dimId, List<GroupItem> items) {
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(dimId);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder).size(0);
        AggregationBuilder rangeBuilder = getNumberAggregation(items, dimId);
        searchSourceBuilder.aggregation(rangeBuilder);
        return new SearchRequest(indexNameInfo.getDataDate())
                .types(indexNameInfo.getIndexType())
                .source(searchSourceBuilder);
    }

    default  SearchRequest getCustomizeDateSearchRequest(IndexNameInfo indexNameInfo, String dimId, List<GroupItem> items) {
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(dimId);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder).size(0);
        AggregationBuilder rangeBuilder = getDateAggregation(items, dimId);
        searchSourceBuilder.aggregation(rangeBuilder);
        return new SearchRequest(indexNameInfo.getDataDate())
                .types(indexNameInfo.getIndexType())
                .source(searchSourceBuilder);
    }

    default BucketOrder getBucketOrder(DimMonitorDetailModel model) {
        BucketOrder bucketOrder = BucketOrder.key(false);
        if (StringUtils.isNotBlank(model.getSortDate()) && model.getSort() != null) {
            bucketOrder = BucketOrder.count(model.getSort());
        }
        return bucketOrder;
    }

    default String getDimIdColumn(String dimId, String date) {
        return dimId + "_" + date;
    }


    default void sort(String classify, List<DimAnalysisRsp.Info> data) {
        if(StringUtils.equals(classify,"03")){
            data.sort((o1, o2) -> {
                Double v1 = getValue(o1.getTitle());
                Double v2 = getValue(o2.getTitle());
                return v1.compareTo(v2);
            });
        }
        if(StringUtils.equals(classify,"05")){
            data.sort((o1, o2) -> {
                String title1 = o1.getTitle();
                String title2 = o2.getTitle();
                if(StringUtils.contains(title1,"-∞")||StringUtils.contains(title2,"+∞")){
                    return -1;
                }
                if(StringUtils.contains(title1,"+∞")||StringUtils.contains(title2,"-∞")){
                    return 1;
                }
                return StringUtils.compare(title1, title2);
            });
        }
    }
}
